import { Controller, IArticleWhere, IArticle } from "egg";
import * as path from "path";
import * as fs from "fs";
const fsPromise = require("fs").promises;

export default class ArticlesController extends Controller {
  mysql = this.app.mysql as any;
  public async index() {
    const admin = this.ctx.user_id === undefined ? false : true;
    const { ctx } = this;
    const query = ctx.request.query;
    // let {pagesize, offset, order, reverse, category, author} = query;
    const pagesize = parseInt(query.pagesize) || 5; //若无此参数则默认为5
    const offset = parseInt(query.offset) || 0; // 若无此参数则默认为0
    const reverse: number = parseInt(query.reverse) || 0; // 若无此参数则默认为0
    const { order, category, author, title } = query;
    
    // 无正确分页参数
    if (isNaN(pagesize) && isNaN(offset)) {
      ctx.status = 400;
      ctx.body = {
        code: 0,
        message: "分页参数错误",
      };
    } else {
      // 索引
      const where: IArticleWhere = {
        alias: category,
        author,
        title,
      };
      ctx.helper.deleteUndefined(where);
      console.log('get articles Info:\n', {where}, {order, reverse});
      
      const result = await this.ctx.service.articles.getInfo(
        pagesize,
        offset,
        undefined,
        where,
        order,
        reverse,
        admin
      );
      ctx.body = {
        code: 1,
        message: "成功",
        result,
      };
    }
  }
  public async byId() {
    const admin = this.ctx.user_id === undefined ? false : true;
    const { ctx } = this;
    const id = parseInt(ctx.params.id);
    const query = ctx.request.query;
    // 默认是否文章基本信息，默认包含为0，不包含文章信息
    const hasArticleInfo = !!parseInt(query.hasArticleInfo);
    // 文章信息列名
    const article: any = await this.service.articles.getById(
      id,
      hasArticleInfo,
      admin
    );
    if (article) {
      // 正常查询到结果
      // 包含的图片名称
      const pictureNames: string[] = [];
      try {
        // 读取 ./public/articles/:id 目录下的文件名
        const names = await fsPromise.readdir(
          path.join(this.config.static.dir, "articles", id.toString())
        );
        pictureNames.push(...names);
      } catch (error) {}
      ctx.body = {
        code: 1,
        message: "成功",
        result: {
          article,
          pictures: pictureNames,
        },
      };
      if (!admin){
        // 执行点击量 +1
        await this.mysql.query(`update articles set clicks = clicks +1 where id = ?`,[id])
      }
    } else {
      // 没有找到对应的文章
      ctx.status = 404;
      ctx.body = {
        code: 0,
        message: "未找到对应id的文章",
      };
    }
  }
  public async deleteById() {
    const admin = this.ctx.user_id === undefined ? false : true;
    const { ctx } = this;
    const id = ctx.params.id;
    if (!admin) {
      ctx.status = 401;
      ctx.body = {
        code: 1,
        message: "未登录",
      };
      return;
    }
    const result = await ctx.service.articles.deleteById(id);
    if (!result) {
      ctx.status = 404;
      ctx.body = {
        code: 1,
        message: "未找到对应文件",
      };
      return;
    }
    ctx.status = 204;
    ctx.body = {
      code: 0,
      message: "删除成功",
    };
  }
  // 创建文章
  public async newArticle() {
    const admin = this.ctx.user_id === undefined ? false : true;
    const { ctx } = this;
    const article = ctx.request.body;
    if (!admin) {
      ctx.status = 401;
      ctx.body = {
        code: 1,
        message: "未登录",
      };
      return;
    }

    const createArticleRule = {
      title: "string",
      category_id: "int",
      abstract: "string",
      content: {
        type: "string",
        required: false,
      },
      is_hidden: {
        type: "number",
        required: false,
      },
      pubdate: {
        type: "dateString",
        required: false,
      },
    };
    ctx.validate(createArticleRule, ctx.request.body);
    article.is_hidden = parseInt(article.is_hidden) ? 1 : 0;
    article.content = article.content ? article.content : "";
    const insertId = await ctx.service.articles.create(article as IArticle);
    if (insertId === undefined) {
      ctx.status = 400;
      ctx.body = {
        code: 1,
        message: "未知错误",
      };
      return;
    }

    ctx.body = {
      code: 0,
      message: "成功写入新文章",
      result: {
        article_id: insertId,
      },
    };
  }
  // 修改文章
  public async modify() {
    const admin = this.ctx.user_id === undefined ? false : true;
    const { ctx } = this;
    const { id } = ctx.params;
    const article = ctx.request.body;
    console.log("modify article:",id,"\n","body:\n",article);
    
    if (!admin) {
      ctx.status = 401;
      ctx.body = {
        code: 1,
        message: "未登录",
      };
      return;
    }

    const updateArticleRule = {
      title: {
        type: "string",
        required: false,
      },
      category_id: {
        type: "int",
        required: false,
      },
      abstract: {
        type: "string",
        required: false,
      },
      content: {
        type: "string",
        required: false,
      },
      is_hidden: {
        type: "number",
        required: false,
      },
      pubdate: {
        type: "dateString",
        required: false,
      },
    };
    ctx.validate(updateArticleRule, ctx.request.body);
    const is_hidden = parseInt(article.is_hidden) ? 1 : 0;
    let pubdate: string | undefined;
    try {
      pubdate = new Date(Date.parse(article.pubdate)).toISOString();
    } catch (error) {
      pubdate = undefined;
    }
    const message = await ctx.service.articles.updateById(
      id,
      article.title,
      article.author,
      article.category_id,
      article.abstract,
      article.content,
      is_hidden,
      pubdate
    );
    if (!!message) {
      ctx.body = {
        code: 0,
        message: "成功修改",
        result: message,
      };
    }
  }
  // 上传图片
  public async uploadImage() {
    const admin = this.ctx.user_id === undefined ? false : true;
    const { ctx } = this;
    const id = parseInt(ctx.params.id);
    let filename = path
      .basename(ctx.query.filename ? ctx.query.filename : "")
      .trim();
    const file = ctx.request.files[0];
    console.log(ctx.request.files);
    
    if (!file) {
      ctx.status = 400;
      ctx.body = {
        code: 1,
        message: "文件未上传",
      };
      return;
    }

    filename = filename === "" ? file.filename : filename;
    
    // const name = path.basename(file.filename);
    if (!admin) {
      ctx.status = 401;
      ctx.body = {
        code: 1,
        message: "未登录",
      };
      return;
    }
    this.ctx.validate(
      {
        id: "int",
      },
      { id }
    );
    const count = await this.mysql.count("articles", {
      id,
    });
    if (count === 0) {
      ctx.status = 404;
      ctx.body = {
        code: 1,
        message: "不存在此文章",
      };
      await fsPromise.unlink(file.filepath);
      return;
    }

    // let result;
    try {
      // 处理文件
      const targetDir = path.join(this.config.filePath.articles, id.toString());
      const targetPath = path.join(targetDir, filename);
      // 文件夹不存在，则新建文件夹
      if (!fs.existsSync(targetDir)) {
        await fsPromise.mkdir(targetDir);
      }
      ctx.body = { code: 0 , message: ''};
      // 文件重复性判断
      if (fs.existsSync(targetPath)) {
        await fsPromise.unlink(targetPath);
        ctx.body.message += "同名文件已存在, 将进行替换\n";
      }
      await fsPromise.copyFile(file.filepath, targetPath);
      ctx.body.message += "成功上传图片\n";
    } catch (error) {
      // bad
      console.error(error);
      ctx.status = 500;
      ctx.body = {
        code: 1,
        message: "写入失败",
      };
    } finally {
      await fsPromise.unlink(file.filepath);
    }
  }
}
